#include "udpappender.h"
#include <iostream>

UdpAppender::UdpAppender(LogLevel level, QString strRemoteIp, quint16 nRemotePort):
    BaseAppender(level),
    m_Udp(nullptr),
    m_RemoteIp(strRemoteIp),
    m_RemotePort(nRemotePort)

{
    //创建UDP连接
    QMutexLocker locker(&m_mutex);
    m_Udp = new QUdpSocket();
    if (!m_Udp) {
        std::cerr << "Failed to create QUdpSocket instance" << std::endl;
        return;
    }

    // 作为纯发送端，不需要绑定固定端口，使用系统自动分配的临时端口
    // 仅在需要接收数据时才需要绑定，这里简化实现
    if (!m_Udp->bind()) { // Qt6中bind()无参数时会自动分配端口和地址
        std::cerr << "UDP bind failed! Error:" <<m_Udp->errorString().toStdString() << std::endl;
        std::cerr << "Note: UDP sender may still work despite bind failure" << std::endl;
    } else {
        std::cout<<"UDP sender initialized, local port: "<<m_Udp->localPort()<<std::endl;
    }


}

UdpAppender::~UdpAppender(){
    //清除连接资源
    QMutexLocker locker(&m_mutex);
    if(nullptr != m_Udp){
        m_Udp->close();
        m_Udp->deleteLater();
        m_Udp = nullptr;
    }
}

void UdpAppender::setRemoteAddr(QString strIp, quint16 nPort){
    QMutexLocker locker(&m_mutex);  // 锁定期间，其他线程无法读写共享资源
    m_RemoteIp = strIp;
    m_RemotePort = nPort;
}

void UdpAppender::setEncoding(QStringConverter::Encoding encoding)
{
    QMutexLocker locker(&m_mutex);
    m_encoding = encoding;
}


void UdpAppender::append(LogLevel level, const QString &msg){
    //过滤消息
    if(level < m_level)return ;

    // 2. 锁定共享资源：读取地址、操作socket
    QMutexLocker locker(&m_mutex);
    if (nullptr == m_Udp) return;  // 防止socket已被析构


    // 根据设置的编码转换字符串为字节数组
    QByteArray logData;

    // Qt6 正确用法：通过 QStringEncoder 进行编码（替代直接构造 QStringConverter）
    QStringEncoder encoder(m_encoding, QStringConverter::Flag::Default);
    if (encoder.isValid()) {
        logData = encoder.encode(msg);
    } else {
        logData = msg.toLocal8Bit();
    }

    m_Udp->writeDatagram(logData.constData(),  // 线程安全的发送（锁定下唯一调用）
                         logData.size(),
                         QHostAddress(m_RemoteIp),
                         m_RemotePort);
}









